package uk.ac.strath.cis.metric_spaces.framework;

import java.util.Collection;
import java.util.Set;

import uk.ac.strath.cis.metric_spaces.indices.DiscreteNearestNeighbourQuery;

public abstract class AbstractMetricIndex<E> implements MetricIndex<E> {

    private Distance<E> metric;
    private int size = 0;

    /**
     * @param metric
     */
    public AbstractMetricIndex(Distance<E> metric) {
        setDistance(metric);
    }

    /**
     * @param index
     */
    public AbstractMetricIndex(AbstractMetricIndex<E> index) {
        this(index.metric);
    }

    /**
     * @param metric
     */
    public void setDistance(Distance<E> metric) {
        this.metric = metric;
    }

    /**
     * @param e1
     * @param e2
     * @return
     */
    public double distance(E e1, E e2) {
        return metric.distance(e1, e2);
    }
    
    public double distance(Collection<E> points){
    	return ((MultivariateDistance<E>)metric).distance(points);
    }

    /**
     * @return
     */
    protected Distance<E> getMetric() {
        return metric;
    }

    /**
     * @return
     */
    public int getSize() {
        return size;
    }

    /**
     * Subclasses should extend. Otherwise will break nearest neighbour.
     */
    public void insert(Set<E> elements) {
        if (size > 0)
            throw new IllegalArgumentException();
        size = elements.size();
    }

    /**
     * 
     */
    public Set<E> nearestNeighbourQuery(E element, int number,
            NearestNeighbourQuery<E> nearestQuery) {
        nearestQuery.setIndex(this);
        return nearestQuery.query(element, number);
    }
    
    /**
     * 
     */
    public Set<E> nearestNeighbourQuery(E element, int number){
    	return nearestNeighbourQuery(element, number, new DiscreteNearestNeighbourQuery<E>());
    }
    
    @Override
    public MetricIndex<E> clone(){
		return this.clone();
    	
    }

}
